package pl.smath.operation.basic;

import java.util.Iterator;

import pl.smath.expression.ExponentiationTerm;
import pl.smath.expression.FractionTerm;
import pl.smath.expression.ProductTerm;
import pl.smath.expression.Term;


/**
 * Rozwija wyrazenie (a*b)^n na a^n*b^n
 * 
 * @author klangner
 */
public class ExpMultiplyOp extends Operation{

	/**
	 * @return Nowy obiekt bedacy sumą wyrazen lub null jezeli wyrazenie nie moga byc dodane
	 */
	public Term process(ExponentiationTerm inputTerm){
		
		Term outputTerm = null;
		
		// t1 musi byc iloczynem wyrazen
		if(inputTerm.getBase() instanceof ProductTerm){
			outputTerm = expandProduct((ProductTerm)inputTerm.getBase(), inputTerm.getExponent());
		}
		else if(inputTerm.getBase() instanceof FractionTerm){
			outputTerm = expandFraction((FractionTerm)inputTerm.getBase(), inputTerm.getExponent());
		}

		if(outputTerm != null)
			outputTerm.setNegative(inputTerm.isNegative());

		return outputTerm;
	}

	/**
	 * Podstawa jest iloczynem
	 */
	public Term expandProduct(ProductTerm base, Term exponent){
		
		Iterator<Term> terms = base.getTerms();
		
		ProductTerm outputTerm = new ProductTerm();
		
		while(terms.hasNext()){
			Term srcTerm = terms.next().copy();
			boolean negative = srcTerm.isNegative();
			srcTerm.setNegative(false);
			ExponentiationTerm destTerm = new ExponentiationTerm(srcTerm, exponent);
			destTerm.setNegative(negative);
			
			outputTerm.addTerm(destTerm);
		}
		
		return outputTerm;
	}

	/**
	 * Podstawa jest ułamkiem
	 */
	public Term expandFraction(FractionTerm fraction, Term exponent){

		ExponentiationTerm up = new ExponentiationTerm(fraction.getNumerator(), exponent);
		ExponentiationTerm down = new ExponentiationTerm(fraction.getDenominator(), exponent);
		
		up.setNegative(fraction.getNumerator().isNegative());
		down.setNegative(fraction.getDenominator().isNegative());
		
		return new FractionTerm(up, down);
	}

}
